﻿layui.define(function (exports) {
  "use static";

  var util = {
    getUndefined: function (o, t, f) {
      f = f === undefined ? o : f;
      return o === undefined ? t : f;
    },
    getClass: function (o) {
      if (o === null) return "Null";
      if (o === undefined) return "Undefined";
      return Object.prototype.toString.call(o).slice(8, -1);
    },
    clone: function (obj) {
      var res;
      var oClass = util.getClass(obj);
      if (oClass === "Object") res = {};
      else if (oClass === "Array") res = [];
      else return obj;
      for (var key in obj) {
        if (!obj.hasOwnProperty(key)) continue;
        var copy = obj[key],
          cClass = util.getClass(copy);
        if (cClass === "Object") res[key] = arguments.callee(copy); // 递归调用
        else if (cClass === "Array") res[key] = arguments.callee(copy);
        else res[key] = obj[key];
      }
      return res;
    },
    tpl: function (html, data, openCode, closeCode) {
      if (html === undefined || html === null || typeof html !== "string")
        return html;
      if (!data) data = {};
      if (!openCode) openCode = "{{";
      if (!closeCode) closeCode = "}}";
      var tool = {
        exp: function (str) {
          return new RegExp(str, "g");
        },
        query: function (type, _, __) {
          var types = ["#([\\s\\S])+?", "([^{#}])*?"][type || 0];
          return tool.exp(
            (_ || "") + openCode + types + closeCode + (__ || "")
          );
        },
        escape: function (str) {
          return String(str || "")
            .replace(/&(?!#?[a-zA-Z0-9]+;)/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/'/g, "&#39;")
            .replace(/"/g, "&quot;");
        },
        error: function (e, tplog) {
          console.error("Laytpl Error：" + e + "\n" + (tplog || ""));
        },
        parse: function (tpl, data) {
          var tplog = tpl;
          try {
            var jss = tool.exp("^" + openCode + "#"),
              jsse = tool.exp(closeCode + "$");
            tpl = tpl
              .replace(tool.exp(openCode + "#"), openCode + "# ")
              .replace(tool.exp(closeCode + "}"), "} " + closeCode)
              .replace(/\\/g, "\\\\")
              // 不匹配指定区域的内容
              .replace(
                tool.exp(openCode + "!(.+?)!" + closeCode),
                function (str) {
                  str = str
                    .replace(tool.exp("^" + openCode + "!"), "")
                    .replace(tool.exp("!" + closeCode), "")
                    .replace(
                      tool.exp(openCode + "|" + closeCode),
                      function (tag) {
                        return tag.replace(/(.)/g, "\\$1");
                      }
                    );
                  return str;
                }
              )
              // 匹配JS规则内容
              .replace(/(?="|')/g, "\\")
              .replace(tool.query(), function (str) {
                str = str.replace(jss, "").replace(jsse, "");
                return '";' + str.replace(/\\/g, "") + ';view+="';
              })
              // 匹配普通字段
              .replace(tool.query(1), function (str) {
                var start = '"+(';
                if (str.replace(/\s/g, "") === openCode + closeCode) return "";
                str = str.replace(tool.exp(openCode + "|" + closeCode), "");
                if (/^=/.test(str)) {
                  str = str.replace(/^=/, "");
                  start = '"+_escape_(';
                }
                return start + str.replace(/\\/g, "") + ')+"';
              })
              // 换行符处理
              .replace(/\r\n/g, '\\r\\n" + "')
              .replace(/\n/g, '\\n" + "')
              .replace(/\r/g, '\\r" + "');
            tpl = '"use strict";var view = "' + tpl + '";return view;';
            tpl = new Function("d, _escape_", tpl);
            return tpl(data, tool.escape);
          } catch (e) {
            tool.error(e, tplog);
            return tplog;
          }
        },
      };
      return tool.parse(html, data);
    },
    render: function (option) {
      if (typeof option.url === "string") {
        option.success = function (res) {
          util.render($.extend({}, option, { url: res }));
        };
        if (option.ajax === "ajax") admin.request(option);
        else
          admin.req(
            option.url,
            option.where,
            option.success,
            option.method,
            option
          );
        return;
      }
      var html = util.tpl(
        option.tpl,
        option.url,
        option.open || config.tplOpen,
        option.close || config.tplClose
      );
      $(option.elem).next("[plus-admin-tpl-rs]").remove();
      $(option.elem).after(html);
      $(option.elem).next().attr("plus-admin-tpl-rs", "");
      option.done && option.done(option.url);
    },
  };
  exports("plusUtil", util);
});
